# encoding:utf-8
import grpc

from common.api.tornado_handler import RequestHandler
from common.utils.security import PyCrypto
import json
from common.utils.tasks import TaskInfo
from web_module.handler.log import save_log, get_async_task, save_user_action
from common.utils.session import redis_get
from common.api.rpc_connect_pool import get_connect, destroy_connect


def do_request(rpc_conn, content, module, handler, func):
    # from user_module.rpc.rpc_proto import user_pb2_grpc, user_pb2
    # conn = grpc.insecure_channel(service_info['host'] + ':' + service_info['port'])
    # client = user_pb2_grpc.UserStub(channel=conn)
    # response = client.logout(user_pb2.req(content='jjj'))
    # print(response)

    exec('from %s_module.rpc import %s_pb2, %s_pb2_grpc' % (module, module, module))
    client = eval('%s_pb2_grpc.%sStub(channel=rpc_conn)' % (module, handler.capitalize()))
    try:
        response = eval('client.%s(%s_pb2.req(content=content))' % (func, module))
    except BaseException as e:
        return e.__str__()
    # print(response)
    return response


def do_post(request: RequestHandler, module, handler, func, *args, **kwargs):
    print(request.request.path)
    content = decode_content(request=request.request, session=request.session)

    conn_id, conn = get_connect(service_name=module)
    if not conn_id:
        msg = '获取连接失败: %s' % module
        request.write({
            'code': -2,
            'msg': msg,
        })
        task_info = TaskInfo(
            task_func=save_log,
            params={
                'content': msg,
                'level': 'error',
            }
        )
        get_async_task().put_task(task_info)
        return

    response = do_request(conn, content, module, handler, func)

    if isinstance(response, str):
        if 'StatusCode.UNAVAILABLE' in response or "Stub' object has no attribute '" in response:
            destroy_connect(conn_id)
            return do_post(request, module, module, handler, func, args, kwargs)
        else:
            return request.write({
                'code': -2,
                'msg': response,
            })

    request.write(response.content)

    if redis_get('developer_log_status') == b'on':
        task_info = TaskInfo(
            task_func=save_log,
            params={
                'content': request.request.path
            }
        )
        get_async_task().put_task(task_info)

    # 保存用户操作信息
    task_info = TaskInfo(
        task_func=save_user_action,
        params={
            'request': request,
            'resp': response.content,
        }
    )
    get_async_task().put_task(task_info)


def do_get(request: RequestHandler, module, handler, func, *args, **kwargs):
    do_post(request, module, handler, func, args, kwargs)


def decode_content(request, session):
    for k in request.arguments:
        try:
            request.arguments[k] = request.arguments[k][0].decode()
        except BaseException as e:
            return json.dumps(request.arguments)
    request.arguments['session_id'] = session.session_id

    content = request.arguments.get('c')
    aes_key = session.get('aes_key')
    if not aes_key or not content:
        return json.dumps(request.arguments, ensure_ascii=False)
    aes = PyCrypto(aes_key)
    try:
        content = aes.decrypt(content)
        content = json.loads(content)
        content['session_id'] = session.session_id
        for k in content.keys():
            request.arguments[k] = content[k]
        del request.arguments['c']
    except BaseException as e:
        print(e.__str__())
    return json.dumps(request.arguments)

